﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Data;
using System.ComponentModel.DataAnnotations;

namespace SmartSpace.Silverlight
{
    public delegate bool ValidateEventHandler<T>(T data, out string message);

    public static class ValidationMessage
    {
        /// <summary>
        /// 显示验证信息
        /// </summary>
        /// <param name="frameworkElement"></param>
        /// <param name="message"></param>
        [Obsolete("请使用方法:RegValidate<T>")]
        public static void Show(FrameworkElement frameworkElement, string message)
        {
            ValidationSource source = new ValidationSource(message);
            Binding binding = new Binding("Error")
            {
                Mode = System.Windows.Data.BindingMode.TwoWay,
                NotifyOnValidationError = true,
                ValidatesOnExceptions = true,
                Source = source
            };

            frameworkElement.SetBinding(Control.TagProperty, binding);

            BindingExpression bindingExpression = frameworkElement.GetBindingExpression(Control.TagProperty);

            bindingExpression.UpdateSource();
        }

        /// <summary>
        /// 注册验证信息
        /// </summary>
        /// <typeparam name="T">验证的数据类型</typeparam>
        /// <param name="frameworkElement">验证的控件</param>
        /// <param name="dependencyProperty">验证的属性</param>
        /// <param name="validateEventHandler">验证方法</param>
        public static void RegValidate<T>(this FrameworkElement frameworkElement, DependencyProperty dependencyProperty, ValidateEventHandler<T> validateEventHandler)
        {
            ValidationSource<T> source = new ValidationSource<T>(validateEventHandler);
            Binding binding = new Binding("Error")
            {
                Mode = System.Windows.Data.BindingMode.TwoWay,
                NotifyOnValidationError = true,
                ValidatesOnExceptions = true,
                Source = source
            };
            frameworkElement.SetBinding(dependencyProperty, binding);
        }

        /// <summary>
        /// true通过，false不通过
        /// </summary>
        /// <param name="frameworkElement"></param>
        /// <returns></returns>
        public static bool Validate(this FrameworkElement frameworkElement, DependencyProperty dependencyProperty)
        {
            BindingExpression bindingExpression = frameworkElement.GetBindingExpression(dependencyProperty);

            bindingExpression.UpdateSource();

            return !Validation.GetHasError(frameworkElement);
        }

        public class ValidationSource
        {
            #region Private memebers
            private string m_message;
            #endregion

            public bool IsShowError
            {
                get;
                set;
            }

            public object Error
            {
                get
                {
                    return null;
                }
                set
                {
                    if (value == null)
                    {
                        throw new ValidationException(m_message);
                    }
                }
            }

            public ValidationSource(string message)
            {
                this.m_message = message;
            }
        }

        public class ValidationSource<T>
        {
            private ValidateEventHandler<T> m_validateEventHandler;

            public T Error
            {
                get
                {
                    return default(T);
                }
                set
                {
                    string message;
                    if (!m_validateEventHandler(value, out message))
                    {
                        throw new ValidationException(message);
                    }
                }
            }

            public ValidationSource(ValidateEventHandler<T> validateEventHandler)
            {
                m_validateEventHandler = validateEventHandler;
            }
        }
    }
}
